package com.stmt.analytic.graph.algorithm.bc;

import com.stmt.analytic.graph.algorithm.Pair;
import com.stmt.analytic.graph.algorithm.TimerWatcher;

import java.util.Collection;
import java.util.Map;
import java.util.Objects;

public class BetweennessCentrality {

    private Graph graph;
    private TimerWatcher clock;

    public static final BetweennessCentralityBuilder newBuilder() {
        return new BetweennessCentralityBuilder();
    }

    private BetweennessCentrality() {
    }

    public Map<String, Float> compute() {
        clock = new TimerWatcher();
        clock.startClock();
        graph.allShtstPaths();
        clock.endClock();
        clock.report();
        return graph.getAllBetweenness();
    }

    public String getClosestSource() {
        return graph.getClosestSource();
    }

    public float getCloseness() {
        return graph.getCloseness();
    }

    public String getBetweennestSource() {
        return graph.getBetweennestSource();
    }

    public float getBetweenness() {
        return graph.getBetweenness();
    }


    public static class BetweennessCentralityBuilder {

        private BetweennessCentrality task;
        private Collection<String> vertices;
        private Collection<Pair<String, String>> edges;

        private BetweennessCentralityBuilder() {
            task = new BetweennessCentrality();
        }

        public BetweennessCentralityBuilder withVertices(Collection<String> inputVertices) {
            this.vertices = inputVertices;
            return this;
        }

        public BetweennessCentralityBuilder withEdges(Collection<Pair<String, String>> inputEdges) {
            this.edges = inputEdges;
            return this;
        }

        public BetweennessCentrality build() {
            Objects.requireNonNull(vertices, "Vertices collection is null.");
            Objects.requireNonNull(edges, "Edges collection is null.");
            this.task.graph = new Graph(vertices.size());
            edges.forEach(e -> {
                task.graph.addEdge(e.fst, e.snd);
            });
            return task;
        }
    }
}